package org.fastiot

class Terminal {

    static enum Session {
        Offline(0), Online(1)
        final int value

        private Session(int value) { this.value = value }
    }

    static enum Management {
        Recorded(0), Registered(1), Abandoned(9)
        final int value

        private Management(int value) { this.value = value }
    }

    static enum Disconnect {
        Timeout(0), Command(1)
        final int value

        private Disconnect(int value) { this.value = value }
    }

    static mapWith = "mongo"

    /**
     * 身份认证标识
     */
    String code

    /**
     * 身份认证密码
     */
    String authCode

    /**
     * 隶属型号代码
     * @link Model
     */
    String modelCode
    /**
     * 隶属型号名称
     * @link Model
     */
    String modelName
    /**
     * 隶属分组代码
     * @link Group
     */
    String groupCode
    /**
     * 隶属分组名称
     * @link Group
     */
    String groupName
    static belongsTo = [model: Model, group: Group]

    /**
     * Customized Contents
     * 自定义内容，针对不同领域场景下，各种终端设备的静态信息定制。
     */
    Map<String, Serializable> customizations
    static embedded = ['customizations']

    /**
     * 管理状态
     */
    Management management = Management.Recorded

    /**
     * 实时会话状态
     */
    Session session = Session.Offline

    /**
     * 最后接入时间
     */
    Date lastAccessDate

    /**
     * Last Access (Remote) Address
     * 最后接入（远程）地址
     */
    InetAddress lastAccessAddress

    /**
     * Last Access (Gateway) Point
     * 最后接入（网关）节点
     */
    String lastAccessPoint

    /**
     * Last Disconnected,  Passive timeout or Active command
     * 最后断开方式，会话超时被动断开；主动发送指令断开。
     */
    Disconnect lastDisconnected

    /**
     * Last Warned
     * 最后告警时间
     */
    Date lastWarned

    /**
     * Last Authenticated
     * 最后身份认证时间
     */
    Date lastAuthenticated

    Date dateCreated
    Date lastUpdated

    static constraints = {
        code(blank: false, unique: true)
        authCode(blank: false)
        model(nullable: true)
        modelCode(nullable: true, validator: Terminal.ModelValidator)
        modelName(nullable: true, validator: Terminal.ModelValidator)
        group(nullable: true)
        groupCode(nullable: true, validator: Terminal.GroupValidator)
        groupName(nullable: true, validator: Terminal.GroupValidator)
        customizations(nullable: true)
        management(nullable: false)
        session(nullable: false)
        lastAccessDate(nullable: true, validator: Terminal.SessionHistoriesValidator)
        lastAccessAddress(nullable: true, validator: Terminal.SessionHistoriesValidator)
        lastAccessPoint(nullable: true, validator: Terminal.SessionHistoriesValidator)
        lastAuthenticated(nullable: true)
        lastDisconnected(nullable: true, validator: Terminal.SessionHistoriesValidator)
        lastWarned(nullable: true)
        dateCreated()
        lastUpdated()
    }

    static ModelValidator = { Object val, Terminal obj ->
        (obj.model == null) == (val == null)
    }

    static GroupValidator = { Object val, Terminal obj ->
        (obj.group == null) == (val == null)
    }

    static SessionHistoriesValidator = { Object val, Terminal obj, org.springframework.validation.Errors errors ->
        if (obj.management == Management.Recorded && val)
            errors.rejectValue('management', 'sessionHistoryOfRecordedTerminalMustBeEmpty')
        else if (obj.management != Management.Recorded && val == null)
            errors.rejectValue('management', 'sessionHistoryOfRegisteredTerminalMustBeSet')
    }

    static mapping = {
        lastAccessAddress sqlType: "varchar"
        code index: true, indexAttributes: [unique: true]
        session index: true
    }

    def beforeValidate() {
        if (model) {
            modelCode = model.code
            modelName = model.name
        }

        if (group) {
            groupCode = group.code
            groupName = group.name
        }
    }
}
